package com.study.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT 工具类
 * 功能：
 * 1️生成 Token
 * 2️解析 Token（解密）
 * 3️验证 Token 有效性与过期状态
 */
@Slf4j
@Component
public class JwtUtil {

    // 建议将 secret 放在配置文件中（如 application.yml）
    private final String secret = "this-is-a-very-secure-and-long-secret-key-for-jwt-signing-demo";

    // Token 默认过期时间（单位：秒）
    private final long expiration = 3600L; // 1小时

    /** 获取签名密钥 */
    private SecretKey getSigningKey() {
        return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
    }

    /*生成 JWT Token*/
    public String generateToken(Long userId, String username) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        claims.put("username", username);

        return Jwts.builder()
                .setClaims(claims)
                .setSubject(username)
                .setIssuedAt(new Date()) // 签发时间
                .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000)) // 过期时间
                .signWith(getSigningKey(), SignatureAlgorithm.HS256)
                .compact();
    }

    /*从 Token 中获取用户ID*/
    public Long getUserIdFromToken(String token) {
        Claims claims = getClaimsFromToken(token);
        return claims.get("userId", Long.class);
    }

    /*从 Token 中获取用户名*/
    public String getUsernameFromToken(String token) {
        Claims claims = getClaimsFromToken(token);
        return claims.get("username", String.class);
    }

    /*验证 Token 是否有效*/
    public boolean validateToken(String token) {
        try {
            Claims claims = getClaimsFromToken(token);
            return !isTokenExpired(claims);
        } catch (Exception e) {
            log.error("JWT token 验证失败: {}", e.getMessage());
            return false;
        }
    }

    /*判断 Token 是否过期*/
    private boolean isTokenExpired(Claims claims) {
        return claims.getExpiration().before(new Date());
    }

    /**从 Token 中解析出 Claims（即解密 Token）*/
    public Claims getClaimsFromToken(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(getSigningKey())
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    /*直接解密显示 Token 的全部内容*/
    public void decryptToken(String token) {
        Claims claims = getClaimsFromToken(token);
        System.out.println("===== Token 解密结果 =====");
        System.out.println("用户ID: " + claims.get("userId"));
        System.out.println("用户名: " + claims.get("username"));
        System.out.println("签发时间: " + claims.getIssuedAt());
        System.out.println("过期时间: " + claims.getExpiration());
        System.out.println("===========================");
    }

    /*测试主函数*/
    public static void main(String[] args) throws InterruptedException {
        JwtUtil jwtUtil = new JwtUtil();
        // 生成 Token
        String token = jwtUtil.generateToken(1001L, "adminUser");
        System.out.println("生成的 Token：\n" + token);
        // 验证 Token
        System.out.println("\nToken 是否有效: " + jwtUtil.validateToken(token));
        // 解密 Token
        jwtUtil.decryptToken(token);
        // 模拟过期（演示）
        System.out.println("\n等待 2 秒后再解析...");
        Thread.sleep(2000);
        boolean valid = jwtUtil.validateToken(token);
        System.out.println("重新验证 Token 是否有效: " + valid);
    }
}
